#ifndef STORE_MENU_H_
#define STORE_MENU_H_

#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
#include <vector>
#include <algorithm>	/* AGV on B3 */
//other types
#include "Category.h"
#include "Product.h"
#include "Customer.h"
#include "Cart.h"
#include "Cart_item.h"
#include "Utilities.h"
#include "ShowFindUpdateCPO.h"			/** AGV on C3 part II**/

using namespace std;

namespace Store{   
	
	enum Msg_type{
	Exit_program=1, About_info, About_help, Close_about_box,
	Read_customers, Read_carts, Read_category_products,
	Show_categories, Show_customers, Show_products, Show_carts, Show_cart_items,
	Find_category_sales, Find_customer_sales, Find_product_sales,
	Update_add_cart_item, Update_add_product, Update_add_customer,
	Customers_button, Carts_button, Categories_button, Cart_items_button, Products_button,
	Display_top3Cust,
	Display_window, Menu_bar_cb,
	Graph_carts_sales, Graph_custs_sales,
	Display_top_carts, Display_top_products, Display_top_customers, Close_display_box,			/** MSH on B2 part II**/
	Close_message_box																			/** MSH on C1 part II**/
	};
   
	struct InvalidType : std::runtime_error {
	  InvalidType(): runtime_error("Invalid type data") {}
	};

class Store_menu {
public:
   struct InvalidData : std::runtime_error {
      InvalidData(): runtime_error("Invalid input data format") {}
   };

   struct InvalidFile : std::runtime_error {
      InvalidFile(): runtime_error("Invalid input file name") {}
   };

   /* AGV on B3 */
   struct countCust{
   public:
		countCust(int c, int i) : count(c), cust_id(i){}
		int count;
		int cust_id;
		int get_count(){return count;}
		int get_cust_id() {return cust_id;}
   };


   enum Main_menu_options{ Info=1, Read, Show, Find, Update, Exit }; 


   enum File_type{ Custs=Customers_button, 
					Cats=Categories_button, 
					Prds=Products_button, 
					Carts=Carts_button, 
					Items=Cart_items_button };
   Store_menu();
   
  
   void display_main_menu() const;
   void display_info() const;//display assignment info & your name plus "Project 1"
   void read();		 
   void update();
   void show();
   void find();
   string findTop3Custs();	/* AGV on B3 */
   bool sortTop3Custs(countCust,countCust);	/* AGV on B3 */
   void read_custs(string);
   void read_carts(string);
   void read_catprds(string);
	string*  find_cust_sales();																/** AGV on C3 part II**/
	//bool compare_sales(double,double);																/** AGV on C3 part II**/

   string* getTopProducts (int n);																/** MSH on B2 part II**/
   string* getTopCarts (int n);

   bool isCustEmpty () {																		/** MSH on C1 part II**/
	   return (custs.empty());																	/** MSH on C1 part II**/
   }																							/** MSH on C1 part II**/
   bool isCartEmpty () {																		/** MSH on C1 part II**/
	   return (carts.empty());																	/** MSH on C1 part II**/
   }																							/** MSH on C1 part II**/
   bool isCatEmpty () {																			/** MSH on C1 part II**/
	   return (cats.empty());																	/** MSH on C1 part II**/
   }																							/** MSH on C1 part II**/
   bool isProdEmpty () {																		/** MSH on C1 part II**/
	   return (prods.empty());																	/** MSH on C1 part II**/
   }																							/** MSH on C1 part II**/
   bool isCartItemEmpty () {																	/** MSH on C1 part II**/
	   return (cart_items.empty());																/** MSH on C1 part II**/
   }																							/** MSH on C1 part II**/

	//show functions added to support GUI interface
   string show_button(Msg_type);
   string show_m(Msg_type);

	template <typename T>
	string show_func(T t, string s)
	{
		string r;
		if(0==t.size())
			r = "No "+s+" Data Loaded\n";
		else
			if (s == "Cart"){
				r = "Cart ID\tCust ID\tDate";
				
			}
			else if (s == "Cart Item"){
				r = "ID\tCart ID\tProd ID\tQuantity";
			} else if (s.compare("Category") == 0) {																																																								/** MSH on A2 part II**/
				r = Utilities::padRight("ID", Utilities::CAT_ID_LENGTH) + "\t" + Utilities::padRight("Name", Utilities::CAT_NAME_LENGTH);																																			/** MSH on A2 part II**/
			} else if (s.compare("Customer") == 0) {																																																								/** MSH on A2 part II**/
				r = Utilities::padRight("ID", Utilities::CUST_ID_LENGTH) + "\t" + Utilities::padRight("Name", Utilities::CUST_NAME_LENGTH) + "\t" + Utilities::padRight("Address", Utilities::CUST_ADDRESS_LENGTH);																	/** MSH on A2 part II**/
			} else if (s.compare("Product") == 0) {																																																									/** MSH on A2 part II**/
				r = Utilities::padRight("ID", Utilities::PRD_ID_LENGTH) + "\t" + Utilities::padRight("Cat ID", Utilities::PRD_CATID_LENGTH) + "\t" + Utilities::padRight("Name", Utilities::PRD_NAME_LENGTH) + "\t" + Utilities::padRight("Price", Utilities::PRD_PRICE_LENGTH);	/** MSH on A2 part II**/
			}
			r += "\n==================================================\n\n";

			for(int i=0; i<t.size(); ++i)
			{
				r+=t[i].display();
				r+="\n";
			}
		return r;
	}
private:
   //private data
	vector<Category> cats;
	vector<Product> prods;
	vector<Customer> custs;
	vector<Cart> carts;
	vector<Cart_item> cart_items;

	int get_file_info(ifstream& ist, string prompt, string fn);	//A.1,2,3 merge added a function for common code
	void read_file(ifstream& file, int num_rec, Store_menu::File_type ftype);
	int	count_prods(int cid);	//B.1 count products in a given category
};
} //end namespace Store
#endif //STORE_MENU_H_